home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / WindowMaker / wrlib / context.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-03-30  |  20.5 KB  |  806 lines

  1. /* context.c - X context management
  2.  * 
  3.  *  Raster graphics library
  4.  * 
  5.  *  Copyright (c) 1997, 1998, 1999 Alfredo K. Kojima
  6.  * 
  7.  *  This library is free software; you can redistribute it and/or
  8.  *  modify it under the terms of the GNU Library General Public
  9.  *  License as published by the Free Software Foundation; either
  10.  *  version 2 of the License, or (at your option) any later version.
  11.  *  
  12.  *  This library is distributed in the hope that it will be useful,
  13.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15.  *  Library General Public License for more details.
  16.  *  
  17.  *  You should have received a copy of the GNU Library General Public
  18.  *  License along with this library; if not, write to the Free
  19.  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  */
  21.  
  22. #include <config.h>
  23.  
  24. #include <X11/Xlib.h>
  25. #include <X11/Xutil.h>
  26. #include <X11/Xatom.h>
  27.  
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <assert.h>
  32.  
  33. #include <math.h>
  34.  
  35. #include "StdCmap.h"
  36.  
  37. #include "wraster.h"
  38.  
  39.  
  40. extern void _wraster_change_filter(int type);
  41.  
  42.  
  43. static Bool bestContext(Display *dpy, int screen_number, RContext *context);
  44.  
  45. static RContextAttributes DEFAULT_CONTEXT_ATTRIBS = {
  46.     RC_UseSharedMemory|RC_RenderMode|RC_ColorsPerChannel, /* flags */
  47.     RDitheredRendering,                /* render_mode */
  48.     4,                   /* colors_per_channel */
  49.     0, 
  50.     0,
  51.     0,
  52.     0,
  53.     True,                   /* use_shared_memory */
  54.     RMitchellFilter,
  55.     RUseStdColormap
  56. };
  57.  
  58.  
  59.  
  60. /*
  61.  * 
  62.  * Colormap allocation for PseudoColor visuals:
  63.  * 
  64.  * 
  65.  * switch standardColormap:
  66.  *     none:
  67.  *         allocate colors according to colors_per_channel
  68.  * 
  69.  *     best/default:
  70.  *         if there's a std colormap defined then use it
  71.  * 
  72.  *         else
  73.  *             create a std colormap and set it
  74.  */
  75.  
  76.  
  77.  
  78.  
  79. /*
  80.  *----------------------------------------------------------------------
  81.  * allocateStandardPseudoColor
  82.  *     Creates the internal colormap for PseudoColor, setting the
  83.  * color values according to the supplied standard colormap.
  84.  * 
  85.  * Returns: -
  86.  *
  87.  * Side effects: -
  88.  *
  89.  * Notes: -
  90.  *----------------------------------------------------------------------
  91.  */
  92. static Bool
  93. allocateStandardPseudoColor(RContext *ctx, XStandardColormap *stdcmap)
  94. {
  95.     int i;
  96.  
  97.     ctx->ncolors = stdcmap->red_max * stdcmap->red_mult
  98.     + stdcmap->green_max * stdcmap->green_mult
  99.     + stdcmap->blue_max * stdcmap->blue_mult + 1;
  100.  
  101.     if (ctx->ncolors <= 1) {
  102.     RErrorCode = RERR_INTERNAL;
  103.     puts("wraster: bad standard colormap");
  104.  
  105.     return False;
  106.     }
  107.     
  108.     ctx->colors = malloc(sizeof(XColor)*ctx->ncolors);
  109.     if (!ctx->colors) {
  110.     RErrorCode = RERR_NOMEMORY;
  111.  
  112.     return False;
  113.     }
  114.     
  115.     ctx->pixels = malloc(sizeof(unsigned long)*ctx->ncolors);
  116.     if (!ctx->pixels) {
  117.     
  118.     free(ctx->colors);
  119.     ctx->colors = NULL;
  120.     
  121.     RErrorCode = RERR_NOMEMORY;
  122.  
  123.     return False;
  124.     }
  125.  
  126.     
  127. #define calc(max,mult) (((i / stdcmap->mult) % \
  128.                          (stdcmap->max + 1)) * 65535) / stdcmap->max
  129.  
  130.     for (i = 0; i < ctx->ncolors; i++) {
  131.     ctx->colors[i].pixel = i + stdcmap->base_pixel;
  132.     ctx->colors[i].red = calc(red_max, red_mult);
  133.     ctx->colors[i].green = calc(green_max, green_mult);
  134.     ctx->colors[i].blue = calc(blue_max, blue_mult);
  135.     
  136.     ctx->pixels[i] = ctx->colors[i].pixel;
  137.     }
  138.  
  139. #undef calc
  140.  
  141.     return True;
  142. }
  143.  
  144.  
  145. static Bool
  146. setupStandardColormap(RContext *ctx, Atom property)
  147. {
  148.     if (!XmuLookupStandardColormap(ctx->dpy, ctx->screen_number,
  149.                    ctx->visual->visualid,
  150.                    ctx->depth, property,
  151.                    True, True)) {
  152.     RErrorCode = RERR_STDCMAPFAIL;
  153.     
  154.     return False;
  155.     }
  156.     return True;
  157. }
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167. static Bool
  168. allocatePseudoColor(RContext *ctx)
  169. {
  170.     XColor *colors;
  171.     XColor avcolors[256];
  172.     int avncolors;
  173.     int i, ncolors, r, g, b;
  174.     int retries;
  175.     int cpc = ctx->attribs->colors_per_channel;
  176.     
  177.     ncolors = cpc * cpc * cpc;
  178.     
  179.     if (ncolors > (1<<ctx->depth)) {
  180.     /* reduce colormap size */
  181.     cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
  182.     ncolors = cpc * cpc * cpc;
  183.     }
  184.  
  185.     assert(cpc >= 2 && ncolors <= (1<<ctx->depth));
  186.  
  187.     colors = malloc(sizeof(XColor)*ncolors);
  188.     if (!colors) {
  189.     RErrorCode = RERR_NOMEMORY;
  190.     return False;
  191.     }
  192.  
  193.     ctx->pixels = malloc(sizeof(unsigned long)*ncolors);
  194.     if (!ctx->pixels) {
  195.     free(colors);
  196.     RErrorCode = RERR_NOMEMORY;
  197.     return False;
  198.     }
  199.     
  200.     i=0;
  201.  
  202.     if ((ctx->attribs->flags & RC_GammaCorrection) && ctx->attribs->rgamma > 0
  203.     && ctx->attribs->ggamma > 0 && ctx->attribs->bgamma > 0) {
  204.     double rg, gg, bg;
  205.     double tmp;
  206.  
  207.     /* do gamma correction */
  208.     rg = 1.0/ctx->attribs->rgamma;
  209.     gg = 1.0/ctx->attribs->ggamma;
  210.     bg = 1.0/ctx->attribs->bgamma;
  211.     for (r=0; r<cpc; r++) {
  212.         for (g=0; g<cpc; g++) {
  213.         for (b=0; b<cpc; b++) {
  214.             colors[i].red=(r*0xffff) / (cpc-1);
  215.             colors[i].green=(g*0xffff) / (cpc-1);
  216.             colors[i].blue=(b*0xffff) / (cpc-1);
  217.             colors[i].flags = DoRed|DoGreen|DoBlue;
  218.  
  219.             tmp = (double)colors[i].red / 65536.0;
  220.             colors[i].red = (unsigned short)(65536.0*pow(tmp, rg));
  221.  
  222.             tmp = (double)colors[i].green / 65536.0;
  223.             colors[i].green = (unsigned short)(65536.0*pow(tmp, gg));
  224.  
  225.             tmp = (double)colors[i].blue / 65536.0;
  226.             colors[i].blue = (unsigned short)(65536.0*pow(tmp, bg));
  227.  
  228.             i++;
  229.         }
  230.         }
  231.     }
  232.  
  233.     } else {
  234.     for (r=0; r<cpc; r++) {
  235.         for (g=0; g<cpc; g++) {
  236.         for (b=0; b<cpc; b++) {
  237.             colors[i].red=(r*0xffff) / (cpc-1);
  238.             colors[i].green=(g*0xffff) / (cpc-1);
  239.             colors[i].blue=(b*0xffff) / (cpc-1);
  240.             colors[i].flags = DoRed|DoGreen|DoBlue;
  241.             i++;
  242.         }
  243.         }
  244.     }
  245.     }
  246.     /* try to allocate the colors */
  247.     for (i=0; i<ncolors; i++) {
  248.     if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
  249.         colors[i].flags = 0; /* failed */
  250.     } else {
  251.         colors[i].flags = DoRed|DoGreen|DoBlue;        
  252.     }
  253.     }
  254.     /* try to allocate close values for the colors that couldn't 
  255.      * be allocated before */
  256.     avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
  257.     for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
  258.  
  259.     XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
  260.  
  261.     for (i=0; i<ncolors; i++) {
  262.     if (colors[i].flags==0) {
  263.         int j;
  264.         unsigned long cdiff=0xffffffff, diff;
  265.         unsigned long closest=0;
  266.         
  267.         retries = 2;
  268.         
  269.         while (retries--) {
  270.         /* find closest color */
  271.         for (j=0; j<avncolors; j++) {
  272.             r = (colors[i].red - avcolors[i].red)>>8;
  273.             g = (colors[i].green - avcolors[i].green)>>8;
  274.             b = (colors[i].blue - avcolors[i].blue)>>8;
  275.             diff = r*r + g*g + b*b;
  276.             if (diff<cdiff) {
  277.             cdiff = diff;
  278.             closest = j;
  279.             }
  280.         }
  281.         /* allocate closest color found */
  282.         colors[i].red = avcolors[closest].red;
  283.         colors[i].green = avcolors[closest].green;
  284.         colors[i].blue = avcolors[closest].blue;
  285.         if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
  286.             colors[i].flags = DoRed|DoGreen|DoBlue;
  287.             break; /* succeeded, don't need to retry */
  288.         }
  289. #ifdef DEBUG
  290.         printf("close color allocation failed. Retrying...\n");
  291. #endif
  292.         }
  293.     }
  294.     }
  295.     
  296.     ctx->colors = colors;
  297.     ctx->ncolors = ncolors;
  298.     
  299.     /* fill the pixels shortcut array */
  300.     for (i = 0; i < ncolors; i++) {
  301.     ctx->pixels[i] = ctx->colors[i].pixel;
  302.     }
  303.     
  304.     return True;
  305. }
  306.  
  307.  
  308. static XColor*
  309. allocateGrayScale(RContext *ctx)
  310. {
  311.     XColor *colors;
  312.     XColor avcolors[256];
  313.     int avncolors;
  314.     int i, ncolors, r, g, b;
  315.     int retries;
  316.     int cpc = ctx->attribs->colors_per_channel;
  317.  
  318.     ncolors = cpc * cpc * cpc;
  319.     
  320.     if (ctx->vclass == StaticGray) {
  321.       /* we might as well use all grays */
  322.       ncolors = 1<<ctx->depth;
  323.     } else {
  324.     if ( ncolors > (1<<ctx->depth) ) {
  325.         /* reduce colormap size */
  326.         cpc = ctx->attribs->colors_per_channel = 1<<((int)ctx->depth/3);
  327.         ncolors = cpc * cpc * cpc;
  328.     }
  329.       
  330.     assert(cpc >= 2 && ncolors <= (1<<ctx->depth));
  331.     }
  332.  
  333.     if (ncolors>=256 && ctx->vclass==StaticGray) {
  334.         /* don't need dithering for 256 levels of gray in StaticGray visual */
  335.         ctx->attribs->render_mode = RBestMatchRendering;
  336.     }
  337.  
  338.     colors = malloc(sizeof(XColor)*ncolors);
  339.     if (!colors) {
  340.     RErrorCode = RERR_NOMEMORY;
  341.     return False;
  342.     }
  343.     for (i=0; i<ncolors; i++) {
  344.     colors[i].red=(i*0xffff) / (ncolors-1);
  345.     colors[i].green=(i*0xffff) / (ncolors-1);
  346.     colors[i].blue=(i*0xffff) / (ncolors-1);
  347.     colors[i].flags = DoRed|DoGreen|DoBlue;
  348.     }
  349.     /* try to allocate the colors */
  350.     for (i=0; i<ncolors; i++) {
  351. #ifdef DEBUG
  352.         printf("trying:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
  353. #endif
  354.     if (!XAllocColor(ctx->dpy, ctx->cmap, &(colors[i]))) {
  355.         colors[i].flags = 0; /* failed */
  356. #ifdef DEBUG
  357.         printf("failed:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
  358. #endif
  359.     } else {
  360.         colors[i].flags = DoRed|DoGreen|DoBlue;        
  361. #ifdef DEBUG
  362.         printf("success:%x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue);
  363. #endif
  364.     }
  365.     }
  366.     /* try to allocate close values for the colors that couldn't 
  367.      * be allocated before */
  368.     avncolors = (1<<ctx->depth>256 ? 256 : 1<<ctx->depth);
  369.     for (i=0; i<avncolors; i++) avcolors[i].pixel = i;
  370.  
  371.     XQueryColors(ctx->dpy, ctx->cmap, avcolors, avncolors);
  372.  
  373.     for (i=0; i<ncolors; i++) {
  374.     if (colors[i].flags==0) {
  375.         int j;
  376.         unsigned long cdiff=0xffffffff, diff;
  377.         unsigned long closest=0;
  378.         
  379.         retries = 2;
  380.         
  381.         while (retries--) {
  382.         /* find closest color */
  383.         for (j=0; j<avncolors; j++) {
  384.             r = (colors[i].red - avcolors[i].red)>>8;
  385.             g = (colors[i].green - avcolors[i].green)>>8;
  386.             b = (colors[i].blue - avcolors[i].blue)>>8;
  387.             diff = r*r + g*g + b*b;
  388.             if (diff<cdiff) {
  389.             cdiff = diff;
  390.             closest = j;
  391.             }
  392.         }
  393.         /* allocate closest color found */
  394. #ifdef DEBUG
  395.         printf("best match:%x,%x,%x => %x,%x,%x\n",colors[i].red,colors[i].green,colors[i].blue,avcolors[closest].red,avcolors[closest].green,avcolors[closest].blue);
  396. #endif
  397.         colors[i].red = avcolors[closest].red;
  398.         colors[i].green = avcolors[closest].green;
  399.         colors[i].blue = avcolors[closest].blue;
  400.         if (XAllocColor(ctx->dpy, ctx->cmap, &colors[i])) {
  401.             colors[i].flags = DoRed|DoGreen|DoBlue;
  402.             break; /* succeeded, don't need to retry */
  403.         }
  404. #ifdef DEBUG
  405.         printf("close color allocation failed. Retrying...\n");
  406. #endif
  407.         }
  408.     }
  409.     }
  410.     return colors;
  411. }
  412.  
  413.  
  414. static Bool
  415. setupPseudoColorColormap(RContext *context)
  416. {
  417.     Atom property = 0;
  418.     
  419.     if (context->attribs->standard_colormap_mode == RCreateStdColormap) {
  420.     property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
  421.     
  422.     if (!setupStandardColormap(context, property)) {
  423.         return False;
  424.     }
  425.     }
  426.  
  427.     if (context->attribs->standard_colormap_mode != RIgnoreStdColormap) {
  428.     XStandardColormap *maps;
  429.     int count, i;
  430.  
  431.     if (!property) {
  432.         property = XInternAtom(context->dpy, "RGB_BEST_MAP", False);
  433.         if (!XGetRGBColormaps(context->dpy, 
  434.                   DefaultRootWindow(context->dpy),
  435.                   &maps, &count, property)) {
  436.         maps = NULL;
  437.         }
  438.         
  439.         if (!maps) {
  440.         property = XInternAtom(context->dpy, "RGB_DEFAULT_MAP", False);
  441.         if (!XGetRGBColormaps(context->dpy,
  442.                       DefaultRootWindow(context->dpy),
  443.                       &maps, &count, property)) {
  444.             maps = NULL;
  445.         }
  446.         }
  447.     } else {
  448.         if (!XGetRGBColormaps(context->dpy, 
  449.                   DefaultRootWindow(context->dpy),
  450.                   &maps, &count, property)) {
  451.         maps = NULL;
  452.         }
  453.     }
  454.     
  455.     if (maps) {        
  456.         int theMap = -1;
  457.         
  458.         for (i = 0; i < count; i++) {
  459.         if (maps[i].visualid == context->visual->visualid) {
  460.             theMap = i;
  461.             break;
  462.         }
  463.         }
  464.  
  465.         if (theMap < 0) {
  466.         puts("wrlib: no std cmap found");
  467.         }
  468.  
  469.         if (theMap >= 0
  470.         && allocateStandardPseudoColor(context, &maps[theMap])) {
  471.  
  472.         context->std_rgb_map = XAllocStandardColormap();
  473.         
  474.         *context->std_rgb_map = maps[theMap];
  475.         
  476.         context->cmap = context->std_rgb_map->colormap;
  477.  
  478.         XFree(maps);
  479.  
  480.         return True;
  481.         }
  482.         
  483.         XFree(maps);
  484.     }
  485.     }
  486.     
  487.     context->attribs->standard_colormap_mode = RIgnoreStdColormap;
  488.  
  489.     /* RIgnoreStdColormap and fallback */
  490.     return allocatePseudoColor(context);
  491. }
  492.  
  493.  
  494.  
  495.  
  496. static char*
  497. mygetenv(char *var, int scr)
  498. {
  499.     char *p;
  500.     char varname[64];
  501.  
  502.     sprintf(varname, "%s%i", var, scr);
  503.     p = getenv(varname);
  504.     if (!p) {
  505.     p = getenv(var);
  506.     }
  507.     return p;
  508. }
  509.  
  510.  
  511. static void 
  512. gatherconfig(RContext *context, int screen_n)
  513. {
  514.     char *ptr;
  515.  
  516.     ptr = mygetenv("WRASTER_GAMMA", screen_n);
  517.     if (ptr) {
  518.     float g1,g2,g3;
  519.     if (sscanf(ptr, "%f/%f/%f", &g1, &g2, &g3)!=3 
  520.         || g1<=0.0 || g2<=0.0 || g3<=0.0) {
  521.         printf("wrlib: invalid value(s) for gamma correction \"%s\"\n", 
  522.            ptr);
  523.     } else {
  524.         context->attribs->flags |= RC_GammaCorrection;
  525.         context->attribs->rgamma = g1;
  526.         context->attribs->ggamma = g2;
  527.         context->attribs->bgamma = g3;
  528.     }
  529.     }
  530.     ptr = mygetenv("WRASTER_COLOR_RESOLUTION", screen_n);
  531.     if (ptr) {
  532.     int i;
  533.     if (sscanf(ptr, "%d", &i)!=1 || i<2 || i>6) {
  534.         printf("wrlib: invalid value for color resolution \"%s\"\n",ptr);
  535.     } else {
  536.         context->attribs->flags |= RC_ColorsPerChannel;
  537.         context->attribs->colors_per_channel = i;
  538.     }
  539.     }
  540.     
  541.     ptr = mygetenv("WRASTER_OPTIMIZE_FOR_SPEED", screen_n);
  542.     if (ptr) {
  543.     context->flags.optimize_for_speed = 1;
  544.     } else {
  545.     context->flags.optimize_for_speed = 0;
  546.     }
  547.     
  548. }
  549.  
  550.  
  551. static void
  552. getColormap(RContext *context, int screen_number)
  553. {
  554.     Colormap cmap = None;
  555.     XStandardColormap *cmaps;
  556.     int ncmaps, i;
  557.  
  558.     if (XGetRGBColormaps(context->dpy, 
  559.              RootWindow(context->dpy, screen_number), 
  560.              &cmaps, &ncmaps, XA_RGB_DEFAULT_MAP)) { 
  561.     for (i=0; i<ncmaps; ++i) {
  562.         if (cmaps[i].visualid == context->visual->visualid) {
  563.         puts("ACHOU");
  564.         cmap = cmaps[i].colormap;
  565.         break;
  566.         }
  567.     }
  568.     XFree(cmaps);
  569.     }
  570.     if (cmap == None) {
  571.     XColor color;
  572.     
  573.     cmap = XCreateColormap(context->dpy, 
  574.                    RootWindow(context->dpy, screen_number),
  575.                    context->visual, AllocNone);
  576.     
  577.     color.red = color.green = color.blue = 0;
  578.     XAllocColor(context->dpy, cmap, &color);
  579.     context->black = color.pixel;
  580.  
  581.     color.red = color.green = color.blue = 0xffff;
  582.     XAllocColor(context->dpy, cmap, &color);
  583.     context->white = color.pixel;
  584.     
  585.     }
  586.     context->cmap = cmap;
  587. }
  588.  
  589.  
  590. static int
  591. count_offset(unsigned long mask) 
  592. {
  593.     int i;
  594.     
  595.     i=0;
  596.     while ((mask & 1)==0) {
  597.     i++;
  598.     mask = mask >> 1;
  599.     }
  600.     return i;
  601. }
  602.  
  603.  
  604. RContext*
  605. RCreateContext(Display *dpy, int screen_number, RContextAttributes *attribs)
  606. {
  607.     RContext *context;
  608.     XGCValues gcv;
  609.  
  610.     
  611.     context = malloc(sizeof(RContext));
  612.     if (!context) {
  613.     RErrorCode = RERR_NOMEMORY;
  614.     return NULL;
  615.     }
  616.     memset(context, 0, sizeof(RContext));
  617.  
  618.     context->dpy = dpy;
  619.     
  620.     context->screen_number = screen_number;
  621.     
  622.     context->attribs = malloc(sizeof(RContextAttributes));
  623.     if (!context->attribs) {
  624.     free(context);
  625.     RErrorCode = RERR_NOMEMORY;
  626.     return NULL;
  627.     }
  628.     if (!attribs)
  629.     *context->attribs = DEFAULT_CONTEXT_ATTRIBS;
  630.     else
  631.     *context->attribs = *attribs;
  632.  
  633.     if (!(context->attribs->flags & RC_StandardColormap)) {
  634.     context->attribs->standard_colormap_mode = RUseStdColormap;
  635.     }
  636.  
  637.     if (!(context->attribs->flags & RC_ScalingFilter)) {
  638.     context->attribs->flags |= RC_ScalingFilter;
  639.     context->attribs->scaling_filter = RMitchellFilter;
  640.     }
  641.  
  642.     /* get configuration from environment variables */
  643.     gatherconfig(context, screen_number);
  644. #ifndef BENCH
  645.     _wraster_change_filter(context->attribs->scaling_filter);
  646. #endif
  647.     if ((context->attribs->flags & RC_VisualID)) {
  648.     XVisualInfo *vinfo, templ;
  649.     int nret;
  650.         
  651.     templ.screen = screen_number;
  652.     templ.visualid = context->attribs->visualid;
  653.     vinfo = XGetVisualInfo(context->dpy, VisualIDMask|VisualScreenMask,
  654.                    &templ, &nret);
  655.     if (!vinfo || nret==0) {
  656.         free(context);
  657.         RErrorCode = RERR_BADVISUALID;
  658.         return NULL;
  659.     }
  660.  
  661.     if (vinfo[0].visual == DefaultVisual(dpy, screen_number)) {
  662.         context->attribs->flags |= RC_DefaultVisual;
  663.     } else {
  664.         XSetWindowAttributes attr;
  665.         unsigned long mask;
  666.         
  667.         context->visual = vinfo[0].visual;
  668.         context->depth = vinfo[0].depth;
  669.         context->vclass = vinfo[0].class;
  670.         getColormap(context, screen_number);
  671.         attr.colormap = context->cmap;
  672.         attr.override_redirect = True;
  673.         attr.border_pixel = 0;
  674.         attr.background_pixel = 0;
  675.         mask = CWBorderPixel|CWColormap|CWOverrideRedirect|CWBackPixel;
  676.         context->drawable =
  677.         XCreateWindow(dpy, RootWindow(dpy, screen_number), 1, 1, 
  678.                   1, 1, 0, context->depth, CopyFromParent,
  679.                   context->visual, mask, &attr);
  680.         /*        XSetWindowColormap(dpy, context->drawable, attr.colormap);*/
  681.     }
  682.     XFree(vinfo);
  683.     }
  684.  
  685.     /* use default */
  686.     if (!context->visual) {
  687.     if ((context->attribs->flags & RC_DefaultVisual)
  688.         || !bestContext(dpy, screen_number, context)) {
  689.         context->visual = DefaultVisual(dpy, screen_number);
  690.         context->depth = DefaultDepth(dpy, screen_number);
  691.         context->cmap = DefaultColormap(dpy, screen_number);
  692.         context->drawable = RootWindow(dpy, screen_number);
  693.         context->black = BlackPixel(dpy, screen_number);
  694.         context->white = WhitePixel(dpy, screen_number);
  695.         context->vclass = context->visual->class;
  696.     }
  697.     }
  698.     
  699.     gcv.function = GXcopy;
  700.     gcv.graphics_exposures = False;
  701.     context->copy_gc = XCreateGC(dpy, context->drawable, GCFunction
  702.                  |GCGraphicsExposures, &gcv);
  703.  
  704.     if (context->vclass == PseudoColor || context->vclass == StaticColor) {
  705.     
  706.     if (!setupPseudoColorColormap(context)) {
  707.         return NULL;
  708.     }
  709.     
  710.     } else if (context->vclass == GrayScale || context->vclass == StaticGray) {
  711.     context->colors = allocateGrayScale(context);
  712.     if (!context->colors) {
  713.         return NULL;
  714.     }
  715.     } else if (context->vclass == TrueColor) {
  716.         /* calc offsets to create a TrueColor pixel */
  717.     context->red_offset = count_offset(context->visual->red_mask);
  718.     context->green_offset = count_offset(context->visual->green_mask);
  719.     context->blue_offset = count_offset(context->visual->blue_mask);
  720.     /* disable dithering on 24 bits visuals */
  721.     if (context->depth >= 24)
  722.         context->attribs->render_mode = RBestMatchRendering;
  723.     }
  724.     
  725.     /* check avaiability of MIT-SHM */
  726. #ifdef XSHM
  727.     if (!(context->attribs->flags & RC_UseSharedMemory)) {
  728.     context->attribs->flags |= RC_UseSharedMemory;
  729.     context->attribs->use_shared_memory = True;
  730.     }
  731.  
  732.     if (context->attribs->use_shared_memory) {
  733.     int major, minor;
  734.     Bool sharedPixmaps;
  735.  
  736.     context->flags.use_shared_pixmap = 0;
  737.  
  738.     if (!XShmQueryVersion(context->dpy, &major, &minor, &sharedPixmaps)) {
  739.         context->attribs->use_shared_memory = False;
  740.     } else {
  741.         if (XShmPixmapFormat(context->dpy)==ZPixmap)
  742.             context->flags.use_shared_pixmap = sharedPixmaps;
  743.     }
  744.     } 
  745. #endif
  746.  
  747.     return context;
  748. }
  749.  
  750.  
  751. static Bool
  752. bestContext(Display *dpy, int screen_number, RContext *context)
  753. {
  754.     XVisualInfo *vinfo=NULL, rvinfo;
  755.     int best = -1, numvis, i;
  756.     long flags;
  757.     XSetWindowAttributes attr;
  758.     
  759.     rvinfo.class  = TrueColor;
  760.     rvinfo.screen = screen_number;
  761.     flags = VisualClassMask | VisualScreenMask;
  762.     
  763.     vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
  764.     if (vinfo) {     /* look for a TrueColor, 24-bit or more (pref 24) */
  765.     for (i=numvis-1, best = -1; i>=0; i--) {
  766.         if (vinfo[i].depth == 24) best = i;
  767.         else if (vinfo[i].depth>24 && best<0) best = i;
  768.     }
  769.     }
  770.  
  771. #if 0
  772.     if (best == -1) {   /* look for a DirectColor, 24-bit or more (pref 24) */
  773.     rvinfo.class = DirectColor;
  774.     if (vinfo) XFree((char *) vinfo);
  775.     vinfo = XGetVisualInfo(dpy, flags, &rvinfo, &numvis);
  776.     if (vinfo) {
  777.         for (i=0, best = -1; i<numvis; i++) {
  778.         if (vinfo[i].depth == 24) best = i;
  779.         else if (vinfo[i].depth>24 && best<0) best = i;
  780.         }
  781.     }
  782.     }
  783. #endif
  784.     if (best > -1) {
  785.     context->visual = vinfo[best].visual;
  786.     context->depth = vinfo[best].depth;
  787.     context->vclass = vinfo[best].class;
  788.     getColormap(context, screen_number);
  789.     attr.colormap = context->cmap;
  790.     attr.override_redirect = True;
  791.     attr.border_pixel = 0;
  792.     context->drawable =
  793.         XCreateWindow(dpy, RootWindow(dpy, screen_number),
  794.               1, 1, 1, 1, 0, context->depth,
  795.               CopyFromParent, context->visual,
  796.               CWBorderPixel|CWColormap|CWOverrideRedirect, &attr);
  797. /*    XSetWindowColormap(dpy, context->drawable, context->cmap);*/
  798.     }
  799.     if (vinfo) XFree((char *) vinfo);
  800.  
  801.     if (best < 0)
  802.     return False;
  803.     else
  804.     return True;
  805. }
  806.